perm filename MMOTNS.PUB[HAL,HE]2 blob
sn#132166 filedate 1974-11-24 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00014 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 .NEWSS MOTIONS
C00003 00003 .mrt: NEWSSS COMPILE-TIME AND RUNTIME CONSIDERATIONS
C00007 00004 .NEWSSS SIMPLE MOVES
C00013 00005 .NEWSSS CONDITION MONITORS
C00024 00006 .NEWSSS FORCE DURING A MOTION
C00032 00007 .dep: NEWSSS DEPROACHES
C00041 00008 .NEWSSS OTHER MOTION CLAUSES
C00049 00009 .NEWSSS COMPLEX MOVES
C00054 00010 .NEWSSS SEARCHES
C00060 00011 .NEWSSS STOPPING
C00061 00012 .NEWSSS DEVICE CONTROL
C00066 00013 .aff: NEWSS AFFIXMENT
C00073 00014 .NEWSSS MOTIONS AND AFFIXMENT
C00076 ENDMK
C⊗;
.NEWSS MOTIONS
Motion statements are at the heart of 'AL; it is by them
that all manipulatory work is done.
.mrt: NEWSSS COMPILE-TIME AND RUNTIME CONSIDERATIONS
All motion statements cause the compiler to make some plans
which will eventually be executed. Those motions which depend on the
value of some frame expressions for intermediate and final position
will be planned using the compile-time planning values for all
relevant expressions. This can lead to inaccurate plans, since at
runtime, some of those expressions might have different values. An
example is an expression involving the location of the arm; the
variables %4yellow%* and %4blue%* are always kept accurate at runtime
by reading the arm locations. Since every arm motion must begin at
the current arm position, this is an implicit parameter to the motion
specification which may not agree with its planning value. This is a special
case of a general
phenomenon: objects are seldom exactly where they
were planned to be, and the runtime value of their frames will very
likely be based on the position of the hand after it successfully
locates the object by sensory feedback.
Thus it becomes necessary that the runtime system adjust all
trajectories immediately before they are executed. Adjusting a
trajectory is less time-consuming than the original calculation;
it makes sense to adjust before each repetition of a motion, whereas
it would be a waste of computer time to recalculate trajectories
that often. Immediately before the arm starts moving on a
trajectory, then, the plan is modified to bring it into line with
current values of frames. If there is any discrepancy between the
runtime and compile-time understanding of where any frame is, the
servo will try to place the arm in the right place nonetheless.
There are limits to the proper use of this feature; if the planning
value is seriously in error (which can happen if the error is but a few
centimeters, depending on the arm being used and its
configuration), then the attempt to make last-minute corrections might
overstrain the arm or impair response to directional
forces. It is the user's responsibility to foresee large
discrepancies in the planning value and to
program in a condition to select one of several possible moves.
Hopefully, this will be seldom needed.
After a motion has been completed, the new location of the hands will
be read, and that will determine the new value for %4yellow%* and
%4blue%*, as well as for any frames which might be affixed to them.
For the moment, we will ignore affixments; they are discussed in great
detail later.
.NEWSSS SIMPLE MOVES
In this section we will discuss motions which are to be
executed on only one arm.
Let us start with an example:
.UNFILL
FRAME frobgrasp, swing1, swing2;
:
MOVE yellow
TO frobgrasp
VIA swing1, swing2
.REFILL
This example demonstrates the general syntax; the reserved word MOVE
is followed by the name of the arm to be moved and a set of clauses,
each beginning with a reserved word (here the words TO and VIA).
There is no punctuation necessary at the end of a clause. The arm is
expected to travel from its current position (wherever that is
planned to be) to the final position (%4frobgrasp%*), passing through
the intermediate positions (%4swing1%* and %4swing2%*). A smooth
trajectory for the motion will be computed by splining together
polynomial segments (usually third degree, occasionally fourth)
separately for each arm joint. This trajectory calculation is
somewhat time-consuming and is done completely at compile time.
Certain things must be specified for any move. First is the
arm which is to be moved. It is named by an arm frame (%4yellow%* or
%4blue%*); other ways of specifying the arm will be mentioned after
the formal idea of affixment has been presented.
Next, the destination frame must be specified. "TO#%4frobgrasp%*"
means that at the end of the motion, the position of the arm should
coincide with the position of %4frobgrasp%*. There is a notational
convenience for destinations: They can be specified in terms of where
the arm is at the start of the motion. The symbol for this is "⊗"
(sometimes pronounced "grinch"), that is, ⊗ is a frame which has the
location and orientation of the arm at the start of the motion.
Thus,
.UNFILL
MOVE yellow TO ⊗ + Z*CM
.REFILL
will move the arm 1 centimeter in Z above its starting place.
.NEWSSS CONDITION MONITORS
During the course of an arm motion, it may be desired to monitor
some condition or set of conditions in order to prematurely stop the
motion or inform some parallel process that a condition has occurred.
The conditions which may be checked are results of measurements, such
as time or force checking, and %4events%*, which are signals that
can be explicitly sent by other simultaneous processes. Events
will be discussed in {sssref evt}; for the time being, assume that
the only conditions which may be checked are measurement conditions.
Here is an example which contains some %4condition monitors%*:
.UNFILL
SCALAR warning;
VECTOR v1;
:
MOVE yellow
TO ypark
ON DURATION ≥ 3*SEC DO warning ← 1
ON FORCE(v1) ≥ 18*OZ DO STOP α{%4Stops the arm%*α}
.REFILL
This motion has two separate and independent condition monitors; the
first will trigger if the motion takes longer than three seconds, and
the second will trigger if the force on the hand, as measured along
vector %4v1%*, exceeds 18 ounces. (Assume we have a macro which
translates ounces into units of force.)
The %4conclusion%* of a condition monitor,
the code which will be executed if the monitor triggers,
is one statement prefaced with the reserved word DO.
A condition monitor has two states: %4enabled%* and
%4disabled%*. Generally, a condition monitor will be enabled as soon as its
motion statement is started, and it becomes disabled when the
motion ends. As soon as a condition monitor triggers, it becomes
disabled unless it becomes explicitly reenabled. Reenabling is done by executing
the statement ENABLE within the conclusion.
In order to enable or disable some arbitrary monitor, it is necessary
to give it a name; this is done by putting a %4label%* immediately
before the word ON. A label is an undeclared identifier followed by
a colon. Thus we could write:
.UNFILL
MOVE blue TO frobgrasp
test1: ON DURATION ≥ 3*SEC DO DISABLE test2
test2: ON TEMPERATURE < 30 DO STOP
.REFILL
Thus, test2 is only performed for the first three seconds.
Occasionally one wants to write a condition monitor which is initially
disabled and becomes enabled later. This is accomplished by putting
the word DEFER before ON:
.UNFILL
fudge: ON temperature > 400 DO
BEGIN α{%4Keep shouting until someone hears.%*α}
WRITE("BURNING");
STOP OVEN; α{%4Pretend we have a device OVEN%*α}
ENABLE α{%4This reenables %*fudgeα}
END
taste: DEFER ON cooked α{%4This is an event.%*α} DO DISABLE fudge
ON DURATION > 30*MIN DO ENABLE taste
.REFILL
It should be noted that this ability to enable and disable
monitors explicitly is a non-structured construct; using it can
lead to unintelligible programs. In any case, scope rules must be
observed; it is not legal to enable or disable monitors across
different MOVE statements. This means that two motion statements
which happen to be simultaneously executing (we shall see how to do this
later, in {sssref cob}) cannot
interfere with each other's condition monitors.
Boolean combinations of conditions are not allowed. Some of the
continually measured functions which may be tested are force along a
vector, (FORCE(V)), force about an axis (TORQUE(V)), time since
beginning of motion (DURATION), and the force between the fingers
(SQUEEZE). One standard event is testable: ARRIVAL. This event
occurs when the motion terminates due to having reached its
destination. It does %4not%* become true if the arm stops for
reasons other than normal arrival at the destination; STOP does not
trigger it.
The conclusion of a condition monitor may be any statement,
including an entire block. The only restriction is that if a motion
statement is the only statement in the conclusion, it must be
surrounded by BEGIN and END. (This is necessary at times to prevent
ambiguity.) The compiler will complain if you try to embed a motion
statement inside another if the result implies simultaneous motion
statements for the same device.
The existence of condition monitors raises this question: When is the
motion really finished? It can happen that the arm itself has stopped,
but some monitor has triggered, and its conclusion is still busy being
executed. The rule is this: the motion is declared done when all the
joints of the arm are stopped, and all monitors are either disabled or
not currently triggered.
Any monitors still enabled, but not triggered, are disabled at the time
that the motion is declared finished.
The user must be aware of some timing considerations.
Firstly, measurements like FORCE, DURATION, and SQUEEZE are not
really computed continually; there is a process which makes a
measurement and then lies dormant for a while (on the order of twenty
milliseconds) before again making a measurement. Thus, monitors do
not trigger immediately when a tested condition becomes true.
Secondly, when a monitor triggers, any initial statements of enabling
or disabling are done immediately, but any arithmetic is scheduled to
be done at some point in the near future. Therefore it is not
possible to guarantee that a critical computation happen immediately.
If the user desires, he may use the word CRITICAL at the start of the
conclusion, and UNCRITICAL at the start of that code which need not
be guaranteed immediate execution. Only one occurrence of CRITICAL,
at the very start of the conclusion, and only one occurrence of
UNCRITICAL are allowed. 'AL automatically assumes CRITICAL before
initial statements of enabling and disabling, and UNCRITICAL
immediately following. An example:
.UNFILL
ON DURATION ≥ 4*SEC DO α{%4Tested frequently%*α}
BEGIN
ENABLE goodguy; α{%4Assumed CRITICAL%*α}
t ← 3; α{%4Assumed UNCRITICAL%*α}
END
ON SQUEEZE ≥ 10*OZ DO α{%4Tested frequently%*α}
BEGIN
CRITICAL; α{%4Overrides defaults%*α}
t ← 4; α{%4Will be done immediately%*α}
UNCRITICAL; α{%4End of critical region%*α}
DISABLE goodguy; α{%4Done soon%*α}
END
.REFILL
.NEWSSS FORCE DURING A MOTION
To make the arm compliant to external forces along some directions or
about some axis it is necessary to specify the appropriate modes of
freedom. Because 'AL works in three-dimensional space, it only
makes sense to specify at most three orthogonal directions and three
orthogonal axes.
In addition to being compliant along degrees of freedom (whether translational
or rotational), it is also useful to apply a fixed force along some of
these degrees. Then pure freedom reduces to application of zero force.
For example,
suppose the arm is on the surface of the station; we wish to apply
a force of 10000 dynes directly downward (the negative Z direction) while
allowing the arm to comply to any horizontal force. This is how
we would write such a motion:
.UNFILL
MOVE blue TO ⊗ α{%4moves nowhere%*α}
WITH DURATION = 10*SEC α{%4give it some time.%*α}
WITH FORCE = -10000*DYNES ALONG Z OF station
WITH FORCE = 0 ALONG X, Y OF station
.REFILL
This example illustrates several conventions. A translational degree
of force (or freedom, if the amount of force is zero) is specified
by the word ALONG followed by a list which can only contain the
vectors X, Y, and Z, followed by the word OF and the name of the
frame which specifies the coordinate system in which the cardinal
axes are to be understood. The amount of force must be in force
units, which are of the scalar dimension
%4mass*distance/(time*time)%*; we
have assumed in the example above that DYNES is a macro which
expands to correct units.
Rotational degrees of force are written in much the same way; the
axes are specified ABOUT a combination of X, Y, and Z OF some frame,
like this:
.UNFILL
WITH FORCE = 5000*DYNES ABOUT Z OF ⊗
.COMT 12
α{Applies a torque about the Z direction of the hand.α}
.END
.REFILL
During a motion which has only translational force specifications, the
orientation of the hand will remain as planned, but the location will
comply with the specified force. During a motion which has rotational
degrees of force, the orientation of the hand will vary from that
planned in accord with the specification and whatever external forces
are encountered.
It does not really make sense to have a force in the nominal direction of motion,
but there is neither a compile-time nor a runtime check to catch such
usage. If it happens, the arm could go into oscillation.
Actually, not all of the full power of force specifications will be available
in the first versions of 'AL. In particular, rotational specifications
will be handled roughly or not at all. Another future embellishment
will be to allow the directions of force to vary during the motion; this
is useful for such tasks as turning a crank. For example, the following
will eventually be available:
.UNFILL
MOVE yellow TO frobgrasp
WITH FORCE = SIN(DURATION*DEG)*10000*DYNES
ALONG Z OF @;
.REFILL
This specifies a varying amount of force along a varying direction:
"@" means "the %4current%* location of the hand, as it changes during
the motion."
Especially at first, some of the force control will be prepared by
the compiler, not calculated during the arm motion itself. Therefore,
if the runtime values of the endpoints of motion are significantly
at odds with their planning values, application of force may go awry.
.dep: NEWSSS DEPROACHES
Many objects have shapes which necessitate care as the arm
approaches them or departs from them. 'AL supplies a method for
insuring that every time the arm approaches a frame, it will pass
through an associated spot first, and every time it leaves that
frame, it passes once again through the same spot. The "spot" is
termed a %4deproach%* (from %4dep%*arture and ap%4proach%*); it is
a transformation to be applied to the frame involved in order to
discover the appropriate place through which to pass.
The fact that a trans is used implies that the deproach point will move
about with its frame. It also means that the location of the deproach
point is relative not to the origin of the frame, but rather to the point
in frame coordinates to which the motion leads. For example, the
deproach transformation of the station is TRANS(VECTOR(0,0,10*CM),NILROT).
If the arm is to go to, say, the point VECTOR(3,1,4)+station
using station's deproach,
then
it will first go through VECTOR(3,1,14). This has the effect of
preventing the arm from going through the surface of the station.
The deproach of a frame is specified by means of an assertion. Without
going into full detail on assertions (which will be covered in detail
in {ssref asr}), we give some examples:
.UNFILL
ASSERT FORM(DEPROACH, station, TRANS(NILROT,VECTOR(0,0,10*CM));
.COMT 12
α{This is preasserted and need never be included.α}
.END
ASSERT FORM(DEPROACH, frob, TRANS(ROT(X,90*DEG),VECTOR(1,0,0)));
.COMT 12
α{Whenever you go to frob, go through a point
90 degrees about frob's X axis from a spot one
centimeter in X from the nominal arrival point.α}
.END
.REFILL
Note that since deproaches are transformations, they have the power to
include rotations. These are considered to be rotations about the
origin of the coordinate system involved; the rotation occurs, as
usual, before translation.
The use of rotations is of marginal use, but is included for completeness.
The deproach points of the departure frame and the arrival frame
are used as implicit VIA points for any motion, except when
the destination is "⊗" or there is an overriding deproach clause
in the motion statement. Here are some examples:
.UNFILL
MOVE yellow TO ⊗; α{%4No departure or approach point used%*α}
MOVE yellow TO frob
WITH APPROACH = NILDEPROACH;
.COMT 20
α{The default departure (which depends on the last
motion made by yellow) is used, but no approach point
is desired.α}
.END
MOVE blue TO frob
WITH DEPARTURE = NILDEPROACH
WITH APPROACH = DEPROACH(frobgrasp);
.COMT 20
α{No departure point is desired, but the approach should be
as if the destination were frobgrasp, not frob.α}
.END
.REFILL
Suppose that a frame
f is given deproach transformation d. It is desired to find the
frame which is the deproach point from some other frame h (for
example, where the hand is, for departure), using f's deproach. The
frame which will be used as a via point is this:
.UNFILL
f * d * (f → station) * h .
.REFILL
The deproach point for f itself is discovered by setting h#=#f in the
above expression. The identities
.UNFILL
(f → station) * f = station, and a * station = a .
.REFILL
reduce the resulting expression to f * d; this is therefore f's own
deproach point.
We have not yet discussed affixment of frames, but the actual decision
of which deproach to use in a given situation depends on it somewhat,
so let us just mention that there is a way to specify that two
frames are affixed, so that whenever on moves, so does the other.
Exact details are given in {ssref aff}. With this understanding,
we can describe the method used to describe how 'AL determines
what deproach to use:
When an arm moves %4to%* a frame,
the frame's own deproach is used, if it has one. If
not, then a search is made along the string of affixments (that is, frames
to which the given frame is affixed are searched) until one is found
which has a deproach. That deproach is the one that is used.
If none at all is found, then the station's
deproach is used as a default. (One way to think of this is to
consider all frames ultimately affixed to the station.) In approaching
a frame which is the result of a calculation, as in
.UNFILL
MOVE yellow TO frob + VECTOR(0,0,1) ,
.REFILL
the default approach is NILDEPROACH.
The default deproach of ⊗ is also null.
In departing %4from%* a frame, it matters whether or not that frame is
now attached to the hand. If not, then the same algorithm used for
finding departure is used for approach. But if the frame
has been detached from some erstwhile mother and is now attached to
the hand, then its old mother's deproach is used (and if there is
none, the same search is made).
Thus, a frame
attached to the hand still has some "memory" of its previous state of
attachment.
.NEWSSS OTHER MOTION CLAUSES
Here we describe some of the other additional clauses that
may be associated with motion statements. The first is WITH
DURATION, which allows the user to specify the timing for the motion.
One can use ≥,=, or ≤ for duration control. The first is used to
guarantee that the motion take a certain amount of time, that is, it
guarantees that the motion will be slow enough so that all the time
is used. The second is rarer; it is used when the exact time is
somehow critical. If the compiler thinks that the arm cannot move
fast enough, it will complain. The third form is included primarily
for completeness; once again, it can cause the compiler to complain.
In the absence of any timing specification, 'AL will compute the
least time which will allow the particular arm being used to move
most efficiently.
VIA is used to name desired
points along the trajectory.
In its simplest form, the VIA clause contains merely a list of frame
expressions, such as in this example:
.UNFILL
MOVE yellow TO finalpoint
VIA int1, int2 + VECTOR(0,0,1), int3;
.REFILL
The motion will be planned to go from the current location of the yellow
arm, through a departure point (if there is one), through each of
the intermediate frames, through the approach point (again, if there
is one), and finally to arrive at finalpoint.
At each of the intermediate points, it is possible to specify
the velocity to be achieved at that point (in terms
of a velocity vector) as well as upper or lower bounds on the time
used to reach this frame from the previous one on the list.
Here is an example demonstrating these features:
.UNFILL
MOVE blue TO finalpoint
VIA int1 WHERE VELOCITY = velo1, DURATION = 3*SEC
VIA int2 WHERE DURATION ≥ 7*SEC
WITH DURATION ≥ 10*SEC;
.REFILL
This specifies two intermediate points, each of which has some condition
associated with it. A time constraint for the entire motion is also
given. Note that the word VIA must be repeated when conditions are
specified for some intermediate point.
One final feature is available with respect to intermediate points:
One may specify that a piece of code is to be initiated when any
intermediate
point is achieved. This is done with a THEN construct:
.UNFILL
MOVE red TO rpark
VIA int1 THEN WRITE("Almost there!")
VIA int2 THEN ENABLE prepare_for_landing;
.REFILL
The statement
following THEN may not be a motion statement for the same
arm; if the statement is a motion statement, it must be surrounded
by BEGIN and END. It is legal to have combinations of velocity,
duration, and THEN-type specifications all at the same intermediate
point.
DIRECTLY is a clause that
tells the compiler that only the via points and the
final point are of interest; no smooth trajectory need be planned.
A smooth motion will result due to runtime calculations.
This will also set the deproaches to NILDEPROACH.
TRACING is another option. It allows the user greater
control over the exact trajectory chosen for the move. The path can
be traced at whatever speed desired. The path, or %4parameterized
frame%*, is a specification of what frame the arm is to go through
for each value of the parameter. It is also possible to specify the
relation between the parameter and real time, as well as the
state the grain of the motion
(that is, how often the actual location should coincide exactly with
the parameterized frame)
or the acceptable tolerance (by a distance scalar).
A glorious and complete example:
.UNFILL
ANGLE SCALAR alpha;
FRAME center;
:
MOVE yellow α{%4No destination specified with a tracing motion.%*α}
TRACING center + 12*VECTOR(COS(alpha),SIN(alpha),0)
FOR alpha ← 0 BY 10*DEG UNTIL 360*DEG
WITHIN .1*CM α{%4This is the tolerance.%*α}
WITH DURATION = 10*SEC;
.REFILL
This specifies a circular motion of radius twelve centimeters parallel
to the surface of the station, about the frame %4center%*. Every
10 degrees, the arm should actually be in the right place, and, furthermore,
it should never be more than .1 centimeter (pretty tight tolerance, actually;
most likely beyond the capability of the manipulator) from the perfect
circle.
The option MAINTAINING ORIENTATION causes
the trajectory computed by 'AL to try to maintain the same
hand orientation throughout the motion. Of course, the final
orientation must be the same as the initial orientation for this to
work at all.
.NEWSSS COMPLEX MOVES
A complex move is one which involves more than one arm at a
time. A distinction can be made between moves which merely require
simultaneous acquisition of "agreement points" (let us call this weak
synchrony), and those which require true coordinated motion
throughout (strong synchrony).
Weak synchrony is achieved by pairing frames to make composite
VIA points and destinations. A paired frame has the form: [F1 : F2].
Here is an example of a move statement using paired frames:
.UNFILL
FRAME y1, y2, y3, y4, b1, b2, b3;
:
MOVE [yellow : blue]
VIA [y1:b1],[y2:],[y3:b2]
TO [y4:b3]
ON [FORCE(Z)>3000*DYNES:] DO STOP
.REFILL
The via list is composed of a set of paired frames, where an empty field
indicates "don't care". In the example shown, the arms start
together, achieve y1 and b1 simultaneously, the yellow arm passes
through y2, and together they pass through y3 and b2.
It is now more cumbersome to specify condition monitors and
conditions in general. The paired construct applies for all the
optional fields; thus, one can write
.UNFILL
WITH FORCE = [14000*DYNES:] ALONG [X OF yellow:]
.REFILL
The meanings of ⊗ and @ are now relative to which side of the
pair they occupy; in the example above, the left side always refers
to the yellow arm, and the right side to the blue. To override this
convention, one may use expressions like "@.yellow", or "⊗.blue".
The meaning of STOP in the example above is extended to both
arms at once; in order to specify only one, it is necessary to say
"STOP yellow" or "STOP blue".
Strong synchrony involves one concept not included above: The
ability to specify the location of one arm throughout the motion in
terms of the location of the other arm. The construct which allows
this specification is COORDINATING; it allows one to give an
expression for the location of one of the two arms. Suppose we wish
to keep both arms in "lockstep", that is, the blue arm should retain
its relative position to the yellow arm throughout the motion. (This
might be necessary for lifting some object by its two ends.) One way
to code this task is as follows:
.UNFILL
FRAME y1, yint1, yint2;
MOVE [yellow : blue]
TO [y1:]
VIA [yint1:],[yint2:]
COORDINATING LOC(blue) = LOC(yellow) + ⊗.blue - ⊗.yellow
WITH FORCE = [:0] ALONG [: X,Y OF blue]
[MAINTAINING ORIENT : MAINTAINING ORIENT]
.REFILL
.NEWSSS SEARCHES
A SEARCH is very much like a move. It is a means of
specifying repeated action in a spiral. As with a MOVE, it is
necessary to name a controllable frame which is to be moved. The ON
construct is exactly as for MOVEs.
Here is a complete example of a search:
.UNFILL
PLANE p1;
:
SEARCH yellow
ACROSS p1
WITH INCREMENT = 3*CM
REPEATING
BEGIN α{%4This is done at each iteration%*α}
FRAME set;
set ← yellow;
MOVE yellow TO ⊗ - Z
ON FORCE(Z) > 3000*DYNES DO TERMINATE;
MOVE yellow TO set DIRECTLY;
END
.REFILL
The plane of the search is specified by the ACROSS construct. A spiral
box search will be performed in this plane (or parallel to it, it the
initial location of the hand is not in the plane); the increment for
the search will be three centimeters. At each point in the search, the
statement following REPEATING is executed; in this case, that involves
two motions. The special statement TERMINATE causes the search to
finally succeed; if there is an ON ARRIVAL clause in the search, it
will trigger when TERMINATE is executed.
It is also possible to terminate a search by setting some flag inside
the repeated code, and to test it in a condition monitor associated
with the search. That monitor can execute the statement STOP, causing
the search to be halted. In this case, any test for ARRIVAL will
never trigger.
.NEWSSS CENTER
Occasionally the hand is positioned around an object, but it
is not certain if it is centered. One wants to close the fingers
slowly, moving the arm meanwhile to accomodate to the location of
the object.
This is accomplished by means of the CENTER command.
The direction that the hand will move is the direction between its
fingers. All that the CENTER command needs is the name of the
arm being moved.
The use of ON is the same as for a
search or any other motion.
Here is a simple example:
.UNFILL
CENTER blue
ON SQUEEZE > 4 DO STOP
.REFILL
Note that this is command, unlike MOVE, treats the fingers and
the arm together as one device.
.NEWSSS CONSTANT VELOCITY MOTION
A special form of the MOVE instruction is provided
to cause the arm to quickly achieve a particular velocity
and to hold it in straight-line motion for a given distance:
.UNFILL
VELOCITY VECTOR vv1;
VECTOR v1;
FRAME dest;
:
MOVE yellow
WITH VELOCITY = vv1
THROUGH dest
FOR DISTANCE = 4*CM .
ON FORCE(v1) > 2000*DYNES DO STOP
.REFILL
The VELOCITY clause tells which vector to follow, and how fast. The
THROUGH clause tells the compiler where the move expects to end. The FOR
DISTANCE tells the maximum distance the hand should go. It is general practice
to terminate such a move by use of a condition monitor.
.NEWSSS STOPPING
Generally, an arm will stop its motion when it has achieved
its destination. Often it is necessary to stop it prematurely, for
example, if some error condition is detected. The statement
.UNFILL
STOP yellow
.REFILL
causes the yellow arm to be unconditionally stopped; any
motion statement operating it will terminate.
This statement may be executed at any point in the program, not just
inside a motion statement.
.NEWSSS DEVICE CONTROL
Each device has a name;
currently, the legal device names are
%4yellow, blue, vice, driver%* (an electric screwdriver), %4yfingers,
bfingers%* (The fingers of the two arms). STOP without any device name
is only legal within a motion command; it stops whatever device(s) that
command is operating. STOP followed by a device name will unconditionally
stop that device.
There is a general command for operating devices other than
arms; it is hoped that this will be flexible enough for any device we
are likely to use (if not, we will add special new forms). Assume we
have the device %4turntable%*, which is capable of moving at any velocity
and for any length of time, but which cannot go to a particular set
point. Then the syntax would be this:
.UNFILL
OPERATE turntable
WITH VELOCITY = 3*DEG/SEC
WITH DURATION = 8*SEC
.REFILL
The idea is that the WITH construct will suffice to account for any
special data (in this case, velocity and duration) peculiar to the
particular device. The OPERATE statement also allows the ON
construct, so it can test for special conditions and take appropriate
actions; it also always allows WITH DURATION.
The screwdriver is a hand-held device which can be run at a
range of speeds, in either direction. By convention, a positive
velocity means clockwise, and a negative velocity means
anticlockwise. The relevant reserved word is VELOCITY, which is
equated with the name of a scalar variable of dimension
%4angle/time%*. This variable will be queried
periodically during the screwdriver motion to determine how much
voltage to apply to the motor. This allows the velocity to change
during the operation of the device, perhaps under the control of a
parallel process which is monitoring some conditions.
An example:
.UNFILL
OPERATE driver
WITH VELOCITY = sp
WITH DURATION = 4*SEC
ON DURATION>2*SEC DO sp ← 2*sp
.COMT 16
α{After two seconds, speed up the screwdriver.α}
.END
.REFILL
Each arm has two fingers at the end which are capable of
closing and opening at various speeds. The relevant reserved words
are OPENING, which is to be set to the desired (distance scalar) opening, and
VELOCITY, which is to be set to the (velocity scalar)
speed desired. It is possible to
refer to the force scalar variable SQUEEZE, which indicates the force being
applied by the fingers.
Condition monitors can also make use of the distance scalar variable
OPENING which will continually reflect the distance between the fingers.
An example:
.UNFILL
OPERATE yfingers
WITH OPENING = 2*IN
WITH VELOCITY = 2*CM/SEC
ON SQUEEZE > 3*OZ DO STOP
ON OPENING ≤ 1*CM DO STOP
.REFILL
.aff: NEWSS AFFIXMENT
.newsss THE AFFIX STATEMENT
Assembly often involves affixing one object to another. 'AL
has a mechanism to automatically keep track of the location of a
subsidiary piece of the assembly as its base is moved; the mechanism
is called %4affixment%*. For example, there might be a frame called
pump and a frame called base. At some stage in the assembly, the
pump is bolted to the base. At this time it is appropriate to
include the statement
.UNFILL
AFFIX pump TO base .
.REFILL
This statement informs the compiler that
motions of base are to affect the location of pump
causes code to be generated for the runtime which will
automatically update the value of pump every time base is changed.
Finally, the planning model will be updated to reflect the affixment.
A slightly more formal definition of affixment, in terms of
explicit assertions and modifications to the runtime graph structure,
is given in {sssref gaf}.
Please note that the AFFIX statement does not act as a library
routine invocation; it does not generate code to actually perform the
bolting operation. The statement merely informs the 'AL system that
at this stage in the execution of the program, pump is to be
considered affixed to base.
If pump should be moved while affixed to base, the value of
base itself will not change, but the affixment will remain for the
new relative positions of pump and base. Occasionally it is desired
that the affixment be symmetric, so that motion of either frame will
cause the other to move. This is done by including the reserved word
RIGIDLY in the affix statement:
.UNFILL
AFFIX pump TO base RIGIDLY
.REFILL
The system uses a trans to store the relative positions
(in our example, (base#α→#pump) ) of the
affixed frames. Normally, the system would invent a
temporary variable to hold this trans; however, the user can
supply his own variable to be used instead, thus allowing his
to modify the affixment relation directly. This is done by including
the phrase "BY#<trans#variable#id>" in the AFFIX statement.
For instance,
.UNFILL
TRANS t1;
:
AFFIX pump TO base BY t1;
.REFILL
If the value of the trans is modified in a non-rigid (that
is, asymmetric) affixment, the effect is to move the subsidiary
frame. If the value of the trans changes in a rigid
(symmetric) affixment, then neither frame will change its value until
one of them explicitly gets a new value; at that time the other will spring
to a new position, as determined by the trans.
The inclusion of the construct "AT#<trans#expression>" will cause
'AL to use the indicated value for the relative affixed position of the
objects. Thus,
.UNFILL
AFFIX pump TO base AT NILTRANS
.bull
is equivalent to
TRANS tempxf;
AFFIX pump TO base BY tempxf;
TEMPXF ← NILTRANS
.Bull
Similarly,
TRANS XF;
AFFIX pump TO base BY xf AT TRANS(NILROT,Z);
.BULL
is equivalent to
TRANS XF;
AFFIX pump TO base BY xf;
xf ← TRANS(NILROT,Z);
.REFILL
It is possible to make chains of affixments, possibly
involving some rigid affixments and some non-rigid ones.
.NEWSSS THE UNFIX STATEMENT
Affixments are undone by the UNFIX statement. For example,
.UNFILL
UNFIX pump FROM base
.REFILL
will remove the affix structure between pump and base, and will discard
the invented trans (unless it was named, of course).
Similarly, the compiler's planning model will be updated to reflect
the fact that pump and base are no longer affixed. However, the
fact that they were previously affixed is important for calculation
of default "deproaches" ({SSREF dep}), and is remembered until either
of the two frames is changes. See {sssref gaf} for a more detailed
description of the assertions actually made do do this.
.NEWSSS MOTIONS AND AFFIXMENT
When some frame has been affixed to an arm, it can be treated
as if it were itself an arm. Thus, the following is legal and useful:
.UNFILL
FRAME frob, frobgrasp;
:
AFFIX frobgrasp TO frob;
AFFIX frob TO yellow;
:
MOVE frobgrasp TO ⊗ + (Z WRT frob);
.REFILL
The effect of this motion statement is to cause the yellow arm
to move in such a way that frobgrasp moves one centimeter
in frob's Z direction. The compiler notices that frobgrasp is
affixed to frob, which in turn is affixed to yellow; furthermore,
it knows the relative positions of each of these, so it is not
too hard to translate the given motion statement into a statement
dealing only with the yellow arm. It is a great convenience to
let the compiler do this translation, which can get messy in the
presence of complicated affixment structures.
The use of "⊗" inside a motion always refers to the frame being treated
as an arm, whether it is actually an arm (blue, yellow) or an affixed
frame (frobgrasp).
If some frame is attached to more than one arm, then it is not legal
to use this feature, because the compiler would have no way of
determining which arm to use. Actually, such an attempt is most
likely an error on the user's part; if an object is affixed to
both arms, then they are joined through that object. It is therefore
not safe to move one arm and not the other. The "right" thing to
do in such a case would be move all the relevant arms to the appropriate
places. We do not intend to implement this at first.